package org.example.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.example.mapper.DBConfigMapper;
import org.example.model.DbConfig;
import org.example.utils.CommonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Component
@Slf4j
public class DataSourceManager {

    private final ConcurrentMap<Long, Object> dataSourceLocks =
            new ConcurrentHashMap<>();

    // 动态数据源Bean
    @Autowired
    private DynamicDataSource dynamicDataSource;

    @Autowired
    private DBConfigMapper dbConfigMapper;

    // 获取租户数据源
    public void loadDataSource(Long subjectId) {

        String dsKey = CommonUtils.getDsKey(subjectId);

        // 第一步：无锁检查
        Map<Object, DataSource> resolvedDataSources = dynamicDataSource.getResolvedDataSources();

        DataSource ds = resolvedDataSources.get(dsKey);
        if (ds != null) {
            //todo  判断当前主题的数据源配置信息是否有变化，如果有变化则需要重新初始化数据源
            //1. 查询当前主题的数据源配置信息
            //2. 对比当前主题的数据源配置信息与缓存中的数据源配置信息
            //3. DruidAbstractDataSource druidAbstractDataSource = (DruidAbstractDataSource) ds;
            //refreshDataSource(subjectId);
            //已初始化过，直接返回
            return;
        }

        // 同步代码块（主题粒度锁）
        synchronized (getSubjectLock(subjectId)) {
            DataSource currentDs = dynamicDataSource.getResolvedDataSources().get(dsKey);
            // 双重检查锁
            if (currentDs == null) {
                // 创建新配置
                createDataSource(subjectId);
            }
        }
    }


    // 刷新数据源（修复版）
    public void refreshDataSource(Long subjectId) {

        synchronized (getSubjectLock(subjectId)) {

            String dsKey = CommonUtils.getDsKey(subjectId);

            // 移除旧数据源
            dynamicDataSource.removeDataSource(dsKey);

            // 获取新配置
            createDataSource(subjectId);

        }
    }


    private void createDataSource(Long subjectId) {

        SubjectContext.setDataSourceKey(CommonUtils.getPrimaryDsKey());
        DbConfig dbConfig = dbConfigMapper.findBySubjectId(subjectId);
        if (dbConfig == null) {
            log.error("数据源配置不存在，租户ID: {}", subjectId);
            return; // 配置不存在时提前返回
        }
        // 创建新数据源
        DataSource ds = createDataSource(dbConfig);

        String dsKey = CommonUtils.getDsKey(subjectId);
        dynamicDataSource.addDataSource(dsKey, ds);

        log.info("主题 {} 数据源刷新完成", subjectId);

    }


    // 动态创建Druid数据源
    private DataSource createDataSource(DbConfig config) {
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl(config.getUrl());
        ds.setUsername(config.getUsername());
        ds.setPassword(config.getPassword());
        ds.setDriverClassName(config.getDriver());
        ds.setInitialSize(2);
        ds.setMinIdle(2);
        ds.setMaxActive(20);
        ds.setMaxWait(60000);
        ds.setValidationQuery("SELECT 1");
        ds.setTestWhileIdle(true);
        try {
            ds.setFilters("stat,wall,slf4j");
        } catch (Exception e) {
            ds.close();
        }
        return ds;
    }


    private Object getSubjectLock(Long subjectId) {
        return dataSourceLocks.computeIfAbsent(subjectId, k -> new Object());
    }
}
